package com.kty.methods.mhys.method.mhys;

import com.kty.methods.mhys.dao.MhysOther;
import com.kty.methods.utils.Utils;
import com.nlf.calendar.Lunar;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Data
public class MeiHua{

    private int year; // 年
    private int month; // 月
    private int day; // 日
    private int time; // 时
    private int minute; // 分
    private int second; // 秒
    private Lunar lunarDate; // 农历日期
    private String lunarDateStr; // 农历日期String格式
    private String solarDate; // 公历日期
    private String baZi; // 八字
    private String baZiWuXing; // 八字五行
    private String baZiNaYin; // 八字纳音
    private String guaMa; // 卦码

    private int yearNumber; // 年数
    private int monthNumber; // 月数
    private int dayNumber; // 日数
    private int timeNumber; // 时数

    private int shangGuaNumber; // 上卦数
    private int xiaGuaNumber; // 下卦数
    private int dongYaoNumber; // 动爻数
    private int bianShangGuaNumber; // 变卦的上卦数
    private int bianXiaGuaNumber; // 变卦的下卦数
    private int huShangGuaNumber; // 互卦的上卦数
    private int huXiaGuaNumber; // 互卦的下卦数

    private String shangGua; // 上卦
    private String xiaGua; // 下卦
    private String dongYao; // 动爻
    private String benGua; // 本卦
    private String bianGua; // 变卦
    private String huGua; // 互卦
    private String cuoGua; // 错卦
    private String zongGua; // 综卦

    private String shangGuaPattern; // 上卦图形
    private String xiaGuaPattern; // 下卦图形
    private String benGuaPattern; // 本卦图形
    private String bianGuaPattern; // 变卦图形
    private String huGuaPattern; // 互卦图形
    private String cuoGuaPattern; // 错卦图形
    private String zongGuaPattern; // 综卦图形
    private String huShangGuaPattern; // 互卦的上卦图形
    private String huXiaGuaPattern; // 互卦的下卦图形

    private String spare; // 备用属性

//**********************************************************************************************************************

    private static final MhysOther mhysOther = new MhysOther();

//======================================================================================================================

    /**
     * 获取并设置'公历日期'
     */
    public void solarDate() {

//        Solar solar = lunarDate.getSolar(); // 获取国历年月日

        int year = lunarDate.getSolar().getYear(); // 获取公历年
        int month = lunarDate.getSolar().getMonth(); // 获取公历月
        int day = lunarDate.getSolar().getDay(); // 获取公历日
        int hour = lunarDate.getSolar().getHour(); // 获取时
        int minute = lunarDate.getSolar().getMinute(); // 获取分
        int second = lunarDate.getSolar().getSecond(); // 获取秒

        setSolarDate(year + "年" + month + "月" + day + "日"  + hour + "时" + minute + "分" + second + "秒");

    }

    /**
     * 获取并设置'农历日期'String格式
     */
    public void lunarDateStr() {

        if(null != getSpare()){
            setLunarDateStr(getLunarDate() + "日(" + getSpare() + ")" + getLunarDate().getTimeZhi() + "时"); // 设置农历日期（附带早晚子时）
        }else {
            setLunarDateStr(getLunarDate() + "日" + getLunarDate().getTimeZhi() + "时"); // 设置农历日期
        }

    }

    /**
     * 获取并设置'八字'
     */
    public void baZi() {
        setBaZi(String.valueOf(lunarDate.getBaZi()));
    }

    /**
     * 获取并设置'八字五行'
     */
    public void baZiWuXing() {
        setBaZiWuXing(String.valueOf(lunarDate.getBaZiWuXing()));
    }

    /**
     * 获取并设置'八字纳音'
     */
    public void baZiNaYin() {
        setBaZiNaYin(String.valueOf(lunarDate.getBaZiNaYin()));
    }

    /**
     * 获取并设置'卦码'
     * ★卦码：上卦数、下卦数、动爻数
     */
    public void guaMa() {
        setGuaMa("" + getShangGuaNumber() + getXiaGuaNumber() + getDongYaoNumber());
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【年数】：根据'年地支'获取
     * <p>
     * ★计算方法：
     * →年数：找出此年的地支，依次对应以下数字：
     * <p>
     * 1   2   3  4	  5	 6	7	8	9	10	11	12
     * 子  丑  寅  卯  辰	 巳	午	未	申	酉	戌	亥
     */
    public void yearNumber() {

        // 获取'年地支'（以正月初一作为新年的开始）
        String yearZhi = lunarDate.getYearZhi();
        // 获取'年地支'对应的数字
        int yearNumber = mhysOther.getDI_ZHI().get(yearZhi);
        // 设置【年数】、【年份】
        setYearNumber(yearNumber);
//        setYear(lunarDate.getYear());

    }

    /**
     * 获取并设置【月数】：根据月份获取
     */
    public void monthNumber() {

        // 获取月份
        int month = lunarDate.getMonth();
        // 设置【月数】、【月份】
        setMonthNumber(month);
//        setMonth(lunarDate.getMonth());

    }

    /**
     * 获取并设置【日数】：根据天数获取
     */
    public void dayNumber() {

        // 获取天数
        int day = lunarDate.getDay();
        // 设置【日数】、【天数】
        setDayNumber(day);
//        setDay(lunarDate.getDay());

    }

    /**
     * 获取并设置【时数】：根据 '时地支' 获取
     */
    public void timeNumber() {

        // 获取'时地支'
        String timeZhi = lunarDate.getTimeZhi();
        // 获取'时地支'对应的数字
        int timeNumber = mhysOther.getDI_ZHI().get(timeZhi);
        // 设置【时数】、【时间】
        setTimeNumber(timeNumber);
//        setTime(lunarDate.getTime().getZhiIndex() + 1);

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【上卦数】：根据（年数 + 月数 + 日数）%8得出的 余数
     */
    public void shangGuaNumber() {

        // 计算【上卦数】：（年数 + 月数 + 日数）%8得出的 余数
        int sgNumber = ((getYearNumber() + getMonthNumber() + getDayNumber()) % 8);

        // 判断是否除尽，若除尽则统一用8来表示
        if (sgNumber == 0) {
            // 设置【上卦数】
            setShangGuaNumber(8);
        } else setShangGuaNumber(sgNumber);

    }

    /**
     * 获取并设置【下卦数】：根据（年数 + 月数 + 日数 + 时数）%8得出的 余数
     */
    public void xiaGuaNumber() {

        // 计算【下卦数】：（年数 + 月数 + 日数 + 时数）%8得出的 余数
        int xgNumber = ((getYearNumber() + getMonthNumber() + getDayNumber() + getTimeNumber()) % 8);

        // 判断是否除尽，若除尽则统一用8来表示
        if (xgNumber == 0) {
            // 设置【下卦数】
            setXiaGuaNumber(8);
        } else setXiaGuaNumber(xgNumber);

    }

    /**
     * 获取并设置【动爻数】：根据（年数 + 月数 + 日数 + 时数）%6得出的 余数
     */
    public void dongYaoNumber() {

        // 计算【动爻数】：（年数 + 月数 + 日数 + 时数）%6得出的 余数
        int dyNumber = ((getYearNumber() + getMonthNumber() + getDayNumber() + getTimeNumber()) % 6);

        // 判断是否除尽，若除尽则统一用6来表示
        if (dyNumber == 0) {
            // 设置【动爻数】
            setDongYaoNumber(6);
        } else setDongYaoNumber(dyNumber);

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【上卦】：根据'上卦数'获取
     */
    public void shangGua() {
        setShangGua(mhysOther.getBA_GUA().get(getShangGuaNumber()));
    }

    /**
     * 获取并设置【上卦】：根据'下卦数'获取
     */
    public void xiaGua() {
        setXiaGua(mhysOther.getBA_GUA().get(getXiaGuaNumber()));
    }

    /**
     * 获取并设置【动爻】：根据'动爻数'获取
     */
    public void dongYao() {
        setDongYao(Utils.shuToHan(getDongYaoNumber()));
    }

    /**
     * 获取并设置【上卦图形】：根据'上卦'获取
     */
    public void shangGuaPattern() {
        setShangGuaPattern(mhysOther.getBA_GUA_TU().get(getShangGua()));
    }

    /**
     * 获取并设置【下卦图形】：根据'下卦'获取
     */
    public void xiaGuaPattern() {
        setXiaGuaPattern(mhysOther.getBA_GUA_TU().get(getXiaGua()));
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 通用：返回（本\互\变）卦图形
     *
     * @param shangGuaNumber 上卦数
     * @param xiaGuaNumber   下卦数
     * @return （本\互\变）卦图形
     */
    protected String getPattern(int shangGuaNumber, int xiaGuaNumber) {

        // 构造key(上卦数+下卦数)，用于查询（本\互\变）卦图型
        List<Integer> key = new ArrayList<>();
        key.add(0, shangGuaNumber);
        key.add(1, xiaGuaNumber);

        // 根据key值获取（本\互\变）卦图形
        return mhysOther.getLIU_SHI_SI_GUA_TU().get(key);

    }

    /**
     * 通用：返回（错\综）卦图形
     *
     * @param index 索引值[0:错卦  1:综卦]
     * @return （错\综）卦图形
     */
    protected String getCuoOrZongPattern(int index) {
        return mhysOther.getCUO_AND_ZONG().get(getBenGuaPattern()).get(index);
    }

    /**
     * 通用：返回（本\互\变\错\综）卦
     *
     * @param guaPattern （本\互\变\错\综）卦图形
     * @return （本\互\变\错\综）卦
     */
    protected String getGua(String guaPattern) {
        return mhysOther.getLIU_SHI_SI_GUA().get(guaPattern);
    }

    /**
     * 通用：判断动爻数区间范围
     *
     * @return true：动爻数为1\2\3   false：动爻数为4\5\6
     */
    protected boolean judgeDongYao() {
        // 【动爻数为(1\2\3)时：上卦不变、下卦变】、【动爻数为(4\5\6)时：上卦变、下卦不变】
        return (getDongYaoNumber() >= 1 && getDongYaoNumber() <= 3);
    }

//-----------------------------------------------------------

    /**
     * 获取并设置【本卦图形】：根据'上卦数'和'下卦数'的组成获取
     */
    public void benGuaPattern() {
        setBenGuaPattern(getPattern(getShangGuaNumber(), getXiaGuaNumber()));
    }

    /**
     * 获取并设置【本卦】：根据'本卦图形'获取
     */
    public void benGua() {
        setBenGua(getGua(getBenGuaPattern()));
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【错卦图形】：根据'本卦图形'变化后获取
     * ★错卦：本卦阳爻变阴爻，阴爻变阳爻
     */
    public void cuoGuaPattern() {
        setCuoGuaPattern(getCuoOrZongPattern(0));
    }

    /**
     * 获取并设置【错卦】：根据'错卦图形'获取
     */
    public void cuoGua() {
        setCuoGua(getGua(getCuoGuaPattern()));
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【综卦图形】：根据'本卦图型'变化后获取
     * ★综卦：将本卦 上下180°旋转变为 综卦
     */
    public void zongGuaPattern() {
        setZongGuaPattern(getCuoOrZongPattern(1));
    }

    /**
     * 获取并设置【综卦】：根据'综卦图形'获取
     */
    public void zongGua() {
        setZongGua(getGua(getZongGuaPattern()));
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 计算变化后的'互卦数据'
     */
    private void hg() {

        // 获取八卦代表图形及其数字
        Map<String, List<Integer>> tushu = mhysOther.getBA_GUA_TUSHU();
        // 获取八卦上中下爻代表数字及其图形
        Map<List<Integer>, String> shutu = mhysOther.getBA_GUA_SHUTU();
        // 获取八卦数
        Map<String, Integer> baGuaShu = mhysOther.getBA_GUA_SHU();

        // 获取本卦中的上卦 [（中、下）爻] 代表的数字
        int upZhongYao = tushu.get(getShangGuaPattern()).get(1); // 上卦中爻（五爻）
        int upXiaYao = tushu.get(getShangGuaPattern()).get(2); // 上卦下爻（四爻）
        // 获取本卦中的下卦 [（上、中）爻] 代表的数字
        int downShangYao = tushu.get(getXiaGuaPattern()).get(0); // 下卦上爻（三爻）
        int downZhongYao = tushu.get(getXiaGuaPattern()).get(1); // 下卦中爻（二爻）

        // ★本卦二三四爻做下卦，三四五卦做上卦
        // 构造新上卦key
        List<Integer> huShangGua = new ArrayList<>();
        huShangGua.add(0, upZhongYao); // 互卦中上卦上爻（六爻） = 原上卦中爻（五爻）
        huShangGua.add(1, upXiaYao); // 互卦中上卦中爻（五爻） = 原上卦下爻（四爻）
        huShangGua.add(2, downShangYao);   // 互卦中上卦下爻（四爻） = 原下卦上爻（三爻）
        // 构造新下卦key
        List<Integer> huXiaGua = new ArrayList<>();
        huXiaGua.add(0, upXiaYao); // 互卦中下卦上爻（五爻） = 原上卦下爻（四爻）
        huXiaGua.add(1, downShangYao); // 互卦中下卦中爻（二爻） = 原下卦上爻（三爻）
        huXiaGua.add(2, downZhongYao); // 互卦中下卦下爻（一爻） = 原下卦中爻（二爻）

        // 获取并设置【互卦的（上、下）卦图】
        String huShangGuaPattern = shutu.get(huShangGua);
        String huXiaGuaPattern = shutu.get(huXiaGua);
        setHuShangGuaPattern(huShangGuaPattern);
        setHuXiaGuaPattern(huXiaGuaPattern);

        // 获取并设置【互卦的（上、下）卦数】
        int huShangGuaNumber = baGuaShu.get(huShangGuaPattern);
        int huXiaGuaNumber = baGuaShu.get(huXiaGuaPattern);
        setHuShangGuaNumber(huShangGuaNumber);
        setHuXiaGuaNumber(huXiaGuaNumber);

    }

    /**
     * 获取并设置【互卦图形】：根据'互卦的上卦数'和'互卦的下卦数'的组成获取
     * ★互卦：本卦二三四爻做下卦，三四五卦做上卦
     */
    public void huGuaPattern() {

        // 计算变化后的 互卦数据
        hg();

        // 获取并设置【互卦图形】
        setHuGuaPattern(getPattern(getHuShangGuaNumber(), getHuXiaGuaNumber()));

    }

    /**
     * 获取并设置【互卦】：根据'互卦图形'获取
     */
    public void huGua() {

        //获取并设置【互卦】
        setHuGua(mhysOther.getLIU_SHI_SI_GUA().get(getHuGuaPattern()));

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 计算变化后的'变卦数据'
     */
    private void bg() {

        // ★判断动爻数
        if (judgeDongYao()) {
            // 根据'下卦数'获取变化后的【下卦数】
            int bianXiaGuaNumber = mhysOther.getBIAN_GUA().get(getXiaGuaNumber()).get(getDongYaoNumber() - 1);
            // 设置【变卦的下卦数】
            setBianXiaGuaNumber(bianXiaGuaNumber);
        } else {
            // 根据'上卦数'获取变化后的【上卦数】
            int bianShangGuaNumber = mhysOther.getBIAN_GUA().get(getShangGuaNumber()).get(getDongYaoNumber() - 4);
            // 设置【变卦的上卦数】
            setBianShangGuaNumber(bianShangGuaNumber);
        }

    }

    /**
     * 获取并设置【变卦图形】：根据'本卦图形'变化后获取
     * ★变卦：根据动爻数变化
     */
    public void bianGuaPattern() {

        // 计算变化后的'变卦数据'
        bg();

        // ★判断动爻数，设置变卦图形
        if (judgeDongYao()) {
            // 动爻数为(1\2\3)时：上卦不变、下卦变
            setBianGuaPattern(getPattern(getShangGuaNumber(), getBianXiaGuaNumber()));
        } else {
            // 动爻数为(4\5\6)时：上卦变、下卦不变
            setBianGuaPattern(getPattern(getBianShangGuaNumber(), getXiaGuaNumber()));
        }

    }

    /**
     * 获取并设置【变卦】：根据'变卦图形'获取
     */
    public void bianGua() {
        setBianGua(getGua(getBianGuaPattern()));
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 判断【用卦、体卦】
     *
     * @param judge         0：上卦  1：下卦
     * @param dongYaoNumber 动爻数
     * @return 用卦\体卦
     */
    public String info(int judge, int dongYaoNumber) {

        // 根据'上下卦'判断（用卦\体卦）
        if (judge == 0) {
            // 判断'动爻数'
            if (dongYaoNumber > 3) {
                // 上卦为：(动)用卦
                return "用卦";
            } else return "体卦";
        } else {
            // 判断'动爻数'
            if (dongYaoNumber <= 3) {
                // 下卦为：(动)用卦
                return "用卦";
            } else return "体卦";
        }

    }

}
